#面向对象编程
    #利用面向对象的思想，可以使得代码更加模块化、可复用、易于维护和扩展。
#类Class：我们将具有相同属性和功能的物体，归纳为一“类”。类是一个抽象概念，它是没实体的。
#对象Object：根据类具象化出来的实体。
    #在人认识世界时，对先有对象，再把对象进行分类
    #在神创造世界时，先定义类，再按类实例化对象

# #1、类的定义
# class Person:           #定义Person类，类名一般首字母大写
#     name='大明'          #定义类的成员属性，name和color
#     color='Yellow'
#     def talk(self):     #定义类的成员方法，talk和hobe
#         print(f'我的名字是{self.name}，皮肤颜色是{self.color}')
#     def hobe(self):
#         print('我的爱好是看书与学习。')
# #2、对象的实例化
#     #类只是一个抽象概念，它默认不执行任何动作
#     #可以根据类实例化出对象来
# p1=Person()         #通过Person类实例化出对象p1
# p1.name='小红'       #对象p1可以对Person类中的成员属性进行使用和修改
# p1.talk()           #对象p1可以对Person类中的成员方法进行使用
#
# p2=Person()         #通过Person类实例化出对象p2
# p2.talk()           #p1修改的成员属性只针对p1有效，对p2没有任何影响
#     #Person类是一个主本，p1和p2都是副本，玩家1和玩家2副本内容一样，但进度独立。

#3、类的继承与多态
# class Father:
#     name='大明'
#     color='Yellow'
#     def talk(self):
#         print(f'我的名字是{self.name}，皮肤颜色是{self.color}')
#     def hobe(self):
#         print('我的爱好是看书与学习。')
# class Son(Father):     #定义子类Son，指明父类是Father
#     name='小明'
#     def hobe(self):
#         print('我的爱好是唱，跳，RAP，篮球')
#
# f1=Father()
# f1.talk()
# f1.hobe()
#     #子类没有talk方法，可以继承父类的talk方法，减少了代码的重复性
#     #子类有hobe方法，可以重写父类的hobe方法，保留了代码的多态性和灵活性
#     #子类有name属性，可以用自己的属性
#     #子类没有color属性，可以继承父类的color属性
# s1=Son()
# s1.talk()
# s1.hobe()


#4、构造函数__init__
    #__init__是类的构造函数，也称初始化函数
    #在实例化对象的时候，就会自动分行构造函数__init__
# class Example4:
#     def __init__(self):
#         print('我是构造函数')
#     def f1(self):
#         print('我的方法1')
# e=Example4()       #实例化对象时就执行__init__，但是不会执行f1

#4.1、构造函数的形参，就是类的形参
class E:        #类没有写形参
    def __init__(self,a,b):     #构造函数写了形参
        print(f'a={a},b={b}')
e=E(5,8)        #实例化对象时，就必须给构造函数传递实参a和b

#4.2、self自身的意思，指明变量是类自己的属性
    #a和b只是外部参数，它只能用在构造函数里
    #如果想要其它的方法也使用a和b，则需要将a和b定义成类内部属性
# class E:
#     c=99        #类中直接定义的属性，默认就是内部属性，但是使用时必须带上self.
#     def __init__(self,a,b):
#         print(f'a={a},b={b}')
#         self.a=a    #把外部参数a的值，赋值给内部属性self.a
#         self.b=b
#     def f1(self):
#         print(f'a={self.a},b={self.b},c={self.c}')
# e=E(5,8)
# e.f1()


#练习：写一个类rectangle，接受两个形参width和height
    #它具备两项功能，求周长perimeter和求面积area
    #要求输入5和8，输出矩形的周长是26，矩形的面积是40
    #要求输入5和10，输出矩形的面积是50
# class Rectangle:
#     def __init__(self,width,height):
#         self.width=width
#         self.height=height
#     def perimeter(self):#周长
#         return 2*(self.width+self.height)
#     def area(self):#面积
#         return self.width*self.height
# t1=Rectangle(5,8)
# print(f'矩形的周长是{t1.perimeter()}，矩形的面积是{t1.area()}')
# t2=Rectangle(5,10)
# print(f'矩形的面积是{t2.area()}')

#练习：写一个类Class班级
    #初始化有3名学生{'1':'孔明','2':'孔暗','3':'孔子'}
    #写一个方法show_stu，展示目前所有的学生
    #写一个方法add_stu，接受2个参数sid和sname，把学生信息添加到学生表中
    #写一个方法del_stu，接受1个参数sid把指定的学生删掉(不考虑sid不存在的情况)
    #1、查看所有的学生信息
    #2、添加4号学生孔融
    #3、查看所有的学生信息
    #4、删除1号学生
    #5、查看所有的学生信息
class Class:
    def __init__(self):
        self.stu={'1':'孔明','2':'孔暗','3':'孔子'}
    def show_stu(self):
        print(self.stu)         #打印字典
    def add_stu(self,sid,sname):
        self.stu[sid]=sname     #添加键值对
    def del_stu(self,sid):
        del self.stu[sid]       #删除键值对
c1=Class()
#1、查看所有的学生信息
c1.show_stu()
#2、添加4号学生孔融
c1.add_stu('4','孔融')
#3、查看所有的学生信息
c1.show_stu()
#4、删除1号学生
c1.del_stu('1')
#5、查看所有的学生信息
c1.show_stu()


#面向过程程序设计的项目结构
    #项目>包>模块>函数
#面向对象程序设计的项目结构
    #项目>包>模块>类>属性和方法